#include "DatabaseMysql.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

DatabaseMysql::DatabaseMysql()
{
    m_mysql = nullptr;
    m_bInit = false;
}

DatabaseMysql::~DatabaseMysql()
{
    if(m_mysql!=nullptr)
    {
        if(m_bInit)
        {
            mysql_close(m_mysql);
        }
    }
}

bool DatabaseMysql::initialize(const std::string &host,const std::string& user,const std::string& pwd,const std::string& dbname)
{
    if(m_bInit)
    {
        mysql_close(m_mysql);
    }

    m_mysql = mysql_init(m_mysql);
    m_mysql = mysql_real_connect(m_mysql,host.c_str(),user.c_str(),pwd.c_str(),dbname.c_str(),0,NULL,0);

    m_DBInfo.strHost = host;
    m_DBInfo.strUser = user;
    m_DBInfo.strPwd  = pwd;
    m_DBInfo.stdDBName = dbname;

    if(m_mysql)
    {
        mysql_query(m_mysql,"set names utf8");
        m_bInit = true;
        return true;
    }
    else
    {
        mysql_close(m_mysql);
    }
    
    return false;

}
 
//这个函数要区分下空数据和出错两种情况
QueryResult* DatabaseMysql::query(const char* sql)
{
    if(!m_mysql)
    {
        if( false == initialize(m_DBInfo.strHost,m_DBInfo.strUser,m_DBInfo.strPwd,m_DBInfo.stdDBName))
        {
            return nullptr;
        }
    }

    if(!m_mysql)
    {
        return nullptr;
    }

    MYSQL_RES* result;
    uint64_t rowCount;
    uint32_t fieldCount;
    {
        int iTempRet = mysql_real_query(m_mysql,sql,strlen(sql));
        if(iTempRet)
        {
            unsigned int nErrno = mysql_errno(m_mysql);
            if(CR_SERVER_GONE_ERROR == nErrno)  //服务器关闭,再尝试打开服务器
            {
                if( false == initialize(m_DBInfo.strHost,m_DBInfo.strUser,m_DBInfo.strPwd,m_DBInfo.stdDBName))
                {
                    return nullptr;
                }

                int iTempRet = mysql_real_query(m_mysql,sql,strlen(sql));
                if(iTempRet)
                {
                    return nullptr;
                }
            }   
            else
            {
                return nullptr;
            }
            
        }

        result = mysql_store_result(m_mysql);
        rowCount = mysql_affected_rows(m_mysql);
        fieldCount = mysql_field_count(m_mysql);
    }

    QueryResult* queryREsult = new QueryResult(result,rowCount,fieldCount);

    queryREsult->nextRow();

    return  queryREsult;
}

QueryResult* DatabaseMysql::query(const std::string& sql)
{
    query(sql.c_str());
}

QueryResult* DatabaseMysql::pQuery(const char* format, ...)
{
    if(!format)
    {
        return nullptr;
    }

    va_list ap;
    char szQuery[MAX_QUERY_LEN];
    va_start(ap,format);
    int res = vsnprintf(szQuery,MAX_QUERY_LEN,format,ap);
    va_end(ap);

    if(res ==-1)
    {
        return nullptr;
    }

    return query(szQuery);
}

bool DatabaseMysql::execute(const char* sql)
{
    if(!m_mysql)
    {
        return false;
    }
    else
    {
        int iTempRet = mysql_real_query(m_mysql,sql,strlen(sql));
        if(iTempRet)
        {
            unsigned int nErrno = mysql_errno(m_mysql);
            if(CR_SERVER_GONE_ERROR == nErrno)  //服务器关闭,再尝试打开服务器
            {
                if( false == initialize(m_DBInfo.strHost,m_DBInfo.strUser,m_DBInfo.strPwd,m_DBInfo.stdDBName))
                {
                    return false;
                }

                int iTempRet = mysql_real_query(m_mysql,sql,strlen(sql));
                if(iTempRet)
                {
                    return false;
                }
                else
                {
                    return true;
                }
                
            }   

            return false;
        }
        else
        {
            return true;
        }
    }
}

bool DatabaseMysql::execute(const char* sql,uint32_t& uAffectedCount,int& nErrno)
{
    if(!m_mysql)
    {
        return false;
    }
    else
    {
        int iTempRet = mysql_query(m_mysql,sql);
        if(iTempRet)
        {
            unsigned int nErrno = mysql_errno(m_mysql);
            if(CR_SERVER_GONE_ERROR == nErrno)  //服务器关闭,再尝试打开服务器
            {
                if( false == initialize(m_DBInfo.strHost,m_DBInfo.strUser,m_DBInfo.strPwd,m_DBInfo.stdDBName))
                {
                    return false;
                }

                int iTempRet = mysql_query(m_mysql,sql);
                nErrno = iTempRet;
                if(iTempRet)
                {
                    return false;
                }
                else
                {
                    return true;
                }
                
            }   

            return false;
        }
        else
        {
            uAffectedCount = static_cast<uint32_t>(mysql_affected_rows(m_mysql));
            return true;
        }
    }
}

bool DatabaseMysql::execute(const char* format, ...)
{
   if(!m_mysql)
    {
        return false;
    }
    else
    {
        va_list ap;
        char szQuery[MAX_QUERY_LEN];
        va_start(ap,format);
        int res = vsnprintf(szQuery,MAX_QUERY_LEN,format,ap);
        va_end(ap);

        int iTempRet = mysql_query(m_mysql,szQuery);
        if(iTempRet)
        {
            unsigned int nErrno = mysql_errno(m_mysql);
            if(CR_SERVER_GONE_ERROR == nErrno)  //服务器关闭,再尝试打开服务器
            {
                if( false == initialize(m_DBInfo.strHost,m_DBInfo.strUser,m_DBInfo.strPwd,m_DBInfo.stdDBName))
                {
                    return false;
                }

                int iTempRet = mysql_query(m_mysql,szQuery);
                if(iTempRet)
                {
                    return false;
                }
                else
                {
                    return true;
                }
                
            }   

            return false;
        }
        else
        {
            return true;
        }
    }
}

uint32_t DatabaseMysql::getInsertID()
{
    return (uint32_t)mysql_insert_id(m_mysql);
}

void DatabaseMysql::clearStoredResults()
{
    if(!m_mysql)
    {
        return;
    }

    MYSQL_RES* result = nullptr;
    while(!mysql_next_result(m_mysql))
    {
        if((result = mysql_store_result(m_mysql)) != nullptr)
        {
            mysql_free_result(result);
        }
    }
}   

int32_t DatabaseMysql::escapeString(char* szDst,const char* szSrc,uint32_t uSize)
{
    if(m_mysql == nullptr )
    {
        return 0;
    }
    else if(szDst == nullptr ||  szSrc == nullptr)
    {
        return 0;
    }

    return mysql_real_escape_string(m_mysql,szDst,szSrc,uSize);
}